package com.education.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.education.platform.config.QwenConfig;
import com.education.platform.dto.ai.*;
import com.education.platform.entity.AiConversation;
import com.education.platform.entity.AiMessage;
import com.education.platform.exception.BusinessException;
import com.education.platform.mapper.AiConversationMapper;
import com.education.platform.mapper.AiMessageMapper;
import com.education.platform.service.AiChatService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AI聊天服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AiChatServiceImpl implements AiChatService {

    private final AiConversationMapper conversationMapper;
    private final AiMessageMapper messageMapper;
    private final QwenConfig qwenConfig;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    @Transactional
    public AiChatResponseDTO chat(AiChatDTO chatDTO, Long userId) {
        Long conversationId = chatDTO.getConversationId();
        
        // 如果需要创建新会话或没有会话ID
        if (chatDTO.getNewConversation() != null && chatDTO.getNewConversation() || conversationId == null) {
            String title = generateTitle(chatDTO.getMessage());
            conversationId = createConversation(userId, title);
        } else {
            // 验证会话是否属于该用户
            AiConversation conversation = conversationMapper.selectById(conversationId);
            if (conversation == null || !conversation.getUserId().equals(userId)) {
                throw new BusinessException(40001, "会话不存在或无权访问");
            }
        }

        // 保存用户消息
        AiMessage userMessage = new AiMessage();
        userMessage.setConversationId(conversationId);
        userMessage.setUserId(userId);
        userMessage.setRole("user");
        userMessage.setContent(chatDTO.getMessage());
        userMessage.setCreatedAt(LocalDateTime.now());
        messageMapper.insert(userMessage);

        // 获取历史消息（最近10条）
        List<AiMessage> historyMessages = messageMapper.selectLatestMessages(conversationId, 10);
        
        // 调用通义千问API
        String aiReply;
        Integer tokens = 0;
        try {
            aiReply = callQwenApi(chatDTO.getMessage(), historyMessages);
            tokens = estimateTokens(chatDTO.getMessage() + aiReply);
        } catch (Exception e) {
            log.error("调用通义千问API失败", e);
            throw new BusinessException(50001, "AI服务调用失败: " + e.getMessage());
        }

        // 保存AI回复
        AiMessage assistantMessage = new AiMessage();
        assistantMessage.setConversationId(conversationId);
        assistantMessage.setUserId(userId);
        assistantMessage.setRole("assistant");
        assistantMessage.setContent(aiReply);
        assistantMessage.setTokens(tokens);
        assistantMessage.setCreatedAt(LocalDateTime.now());
        messageMapper.insert(assistantMessage);

        // 更新会话消息数量
        conversationMapper.updateMessageCount(conversationId);

        // 构建响应
        AiChatResponseDTO response = new AiChatResponseDTO();
        response.setConversationId(conversationId);
        response.setReply(aiReply);
        response.setMessageId(assistantMessage.getId());
        response.setTokens(tokens);

        return response;
    }

    @Override
    public List<AiConversationVO> getConversations(Long userId) {
        List<AiConversation> conversations = conversationMapper.selectByUserId(userId);
        return conversations.stream()
                .map(conv -> {
                    AiConversationVO vo = new AiConversationVO();
                    BeanUtil.copyProperties(conv, vo);
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<AiMessageVO> getMessages(Long conversationId, Long userId) {
        // 验证会话权限
        AiConversation conversation = conversationMapper.selectById(conversationId);
        if (conversation == null || !conversation.getUserId().equals(userId)) {
            throw new BusinessException(40001, "会话不存在或无权访问");
        }

        List<AiMessage> messages = messageMapper.selectByConversationId(conversationId);
        return messages.stream()
                .map(msg -> {
                    AiMessageVO vo = new AiMessageVO();
                    BeanUtil.copyProperties(msg, vo);
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Long createConversation(Long userId, String title) {
        AiConversation conversation = new AiConversation();
        conversation.setUserId(userId);
        conversation.setTitle(title);
        conversation.setStatus(0);
        conversation.setMessageCount(0);
        conversation.setCreatedAt(LocalDateTime.now());
        conversation.setUpdatedAt(LocalDateTime.now());
        
        conversationMapper.insert(conversation);
        return conversation.getId();
    }

    @Override
    @Transactional
    public void deleteConversation(Long conversationId, Long userId) {
        // 验证会话权限
        AiConversation conversation = conversationMapper.selectById(conversationId);
        if (conversation == null || !conversation.getUserId().equals(userId)) {
            throw new BusinessException(40001, "会话不存在或无权访问");
        }

        // 逻辑删除会话
        conversationMapper.deleteById(conversationId);
        
        // 逻辑删除该会话的所有消息
        messageMapper.delete(new LambdaQueryWrapper<AiMessage>()
                .eq(AiMessage::getConversationId, conversationId));
    }

    /**
     * 调用通义千问API
     */
    private String callQwenApi(String userMessage, List<AiMessage> historyMessages) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(qwenConfig.getBaseUrl() + "/chat/completions");
            
            // 设置请求头
            httpPost.setHeader("Authorization", "Bearer " + qwenConfig.getApiKey());
            httpPost.setHeader("Content-Type", "application/json");

            // 构建消息列表
            ArrayNode messages = objectMapper.createArrayNode();
            
            // 添加系统提示
            ObjectNode systemMessage = objectMapper.createObjectNode();
            systemMessage.put("role", "system");
            systemMessage.put("content", "你是一个专业的家教平台AI助手，可以帮助用户解答关于找家教、学习辅导等相关问题。请用友好、专业的态度回答用户的问题。");
            messages.add(systemMessage);
            
            // 添加历史消息（倒序，因为是从数据库最新取的）
            for (int i = historyMessages.size() - 1; i >= 0; i--) {
                AiMessage msg = historyMessages.get(i);
                ObjectNode msgNode = objectMapper.createObjectNode();
                msgNode.put("role", msg.getRole());
                msgNode.put("content", msg.getContent());
                messages.add(msgNode);
            }
            
            // 添加当前用户消息
            ObjectNode currentMessage = objectMapper.createObjectNode();
            currentMessage.put("role", "user");
            currentMessage.put("content", userMessage);
            messages.add(currentMessage);

            // 构建请求体
            ObjectNode requestBody = objectMapper.createObjectNode();
            requestBody.put("model", qwenConfig.getModel());
            requestBody.set("messages", messages);
            requestBody.put("max_tokens", qwenConfig.getMaxTokens());

            String requestJson = objectMapper.writeValueAsString(requestBody);
            log.info("通义千问请求: {}", requestJson);

            httpPost.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON));

            // 发送请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                String responseBody = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8);
                log.info("通义千问响应: {}", responseBody);

                // 解析响应
                JsonNode jsonResponse = objectMapper.readTree(responseBody);
                
                // 检查错误
                if (jsonResponse.has("error")) {
                    String errorMsg = jsonResponse.get("error").get("message").asText();
                    throw new IOException("API错误: " + errorMsg);
                }
                
                // 提取AI回复
                return jsonResponse.get("choices")
                        .get(0)
                        .get("message")
                        .get("content")
                        .asText();
            }
        }
    }

    /**
     * 生成会话标题
     */
    private String generateTitle(String firstMessage) {
        if (StrUtil.isBlank(firstMessage)) {
            return "新对话";
        }
        // 取前20个字符作为标题
        return firstMessage.length() > 20 
                ? firstMessage.substring(0, 20) + "..." 
                : firstMessage;
    }

    /**
     * 估算token数量（简单估算）
     */
    private Integer estimateTokens(String text) {
        // 简单估算：中文字符约1.5 token，英文单词约1 token
        int chineseCount = 0;
        int englishCount = 0;
        
        for (char c : text.toCharArray()) {
            if (c >= 0x4e00 && c <= 0x9fa5) {
                chineseCount++;
            } else if (Character.isLetterOrDigit(c)) {
                englishCount++;
            }
        }
        
        return (int) (chineseCount * 1.5 + englishCount / 4);
    }
}

